#include "18F4620.h"
#include <STDLIB.H>
#include "ms_define.h"

#define ENABLE_I2C_COMM (1)

#fuses H4, NOWDT, PUT, NOLVP, NOXINST, FCMEN
//#fuses HS, NOWDT, PUT, NOLVP, NOXINST, FCMEN
#use delay(clock=40000000)
#use rs232(baud=115200, xmit=PIN_C6, rcv=PIN_C7)
//#use i2c(master, sda=PIN_C4, scl=PIN_C3, FORCE_HW, SLOW/*FAST=100000*/)
#use i2c(master, sda=PIN_C4, scl=PIN_C3, FORCE_HW, FAST=400000)
//#use i2c(master, sda=PIN_C4, scl=PIN_C3, FAST=400000)

#if 1
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
#use fast_io(E)
#endif

#bit    led         = LATC.0
#bit    buzz        = LATA.4
#bit    coil        = LATC.1
#bit    en_out_a    = LATB.7
#bit    en_out_b    = LATB.6

#define MSG_T       (1)     //(s)
#define LED_T       (250)   //(ms)
#define TIME_CNT    ((MSG_T * 1000) / (LED_T * 2)) - 1
#define BATT_MUL    (133.00/33.00)
#define ADC_CONST   (5100.00/1024.00)

#define I2C_DISPLAY_ADR (0xa0)  //i2c dyspaly device address  
#define I2C_TIMEOUT     (5)     //tryes i2c_write to be ack. when it called with dev address

#define adc_to_kpa(adc)((int16)((2.3469*adc) + 190.61))

#include "i2c_sys.h"
#include "test_i2c.h"

int1    RST  = 0;
int16   tmr3 = (0xFFFF-62500);
int1    ms_send_data = 0, loop_test = 0;
variables_t ms_data;

void enable_my_ints (void)
{
//============== INTERRUPTS_SETUP =======================
        //enable_interrupts(INT_TIMER1|INT_AD);
        enable_interrupts(INT_RDA);
        //enable_interrupts(INT_OSCF);
        enable_interrupts(GLOBAL/*|INT_RB*/); // |INT_RDA
}

#INT_TIMER3
void   tmr_3_isr   (void)
{
    set_timer3(tmr3); //interrupt on every 50 ms.
    clear_interrupt(INT_TIMER3);
    coil =! coil;
    return;
}

#INT_RDA
void rx_int (void)
{
    static   unsigned   int8 counter;
    unsigned   int8   rs_tmp,i;
#if 0
    i=uart_err();
    switch (i)
    {
        case 2:
            puts("uart_err2");
            bit_clear(RCSTA,4);
            bit_set(RCSTA,4);
        break;

        case 4:
            puts("uart_err4");
            return;
        break;
    }
#endif
    rs_tmp=getc();
    switch (rs_tmp) {
        case '?':
        case 0x15:   // bootloader start code
            RST=1;   // set reset bit
            reset_cpu();
            break;

        case 'e':
            loop_test =1;
            break;

        case 'd':
            loop_test =0;
            break;

        case 'q':
            tmr3 -= 10;
            break;

        case 'z':
            tmr3 += 10;
            break;

        case 'a':
        case 'A':
            ms_send_data = 1;
            break;

        default:
            putc(rs_tmp);  //terminal echo
            break;
    }
    return;
}

void main (void) {
    int8    cnt     = 0;
    int32   sec     = 0;
    int16   batt_s  = 0;
    int16   kpa_1, kpa_2;
    int1    have_i2c = 0, test_i2c_byte = 0, test_i2c_block = 0;
    int8    i;

    int8    ee_dat[10] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19};

    set_tris_a(0b11101111); //0-out 1-in
    set_tris_c(0b11111101); //0-out 1-in
    set_tris_b(0b00111111); //0-out 1-in
    set_tris_e(0b11111111); //0-out 1-in
    set_tris_d(0x00);       //0-out 1-in

    LATC = 0xFF;

    en_out_a = en_out_b = 0;
    LATD = 0xFF;

    setup_adc(ADC_CLOCK_DIV_64|ADC_TAD_MUL_20); //32/16
    setup_adc_ports(AN0_TO_AN9);

    //============== Tmer 3 settings ==================================
    set_timer3(-62500);
    setup_timer_3(T3_INTERNAL|T3_DIV_BY_8); // T3 runing max time 0,104856 ms
    enable_interrupts(INT_TIMER3);

    enable_my_ints();

    buzz = 0;
    delay_ms(200);
    buzz = 1;
    ms_data.seconds = 0;

#if (1 == ENABLE_I2C_COMM)
    printf("Size of ms_data: %u", sizeof(ms_data));
    printf("Check for i2c ...\r\n");
    if(check_i2c_dev(I2C_DISPLAY_ADR, I2C_TIMEOUT)) {
        printf("i2c adr 0x%X\r\n", I2C_DISPLAY_ADR);
        have_i2c = 1;
    } else {
        printf("err i2c adr 0x%X\r\n", I2C_DISPLAY_ADR);
        have_i2c = 0;
    }
#endif

    while (TRUE) {
        led = 0;
        en_out_a = en_out_b = 0;
        delay_ms(LED_T);
        led = 1;
        en_out_a = en_out_b = 1;
        delay_ms (LED_T);
        if (cnt++ > TIME_CNT && loop_test) {
        cnt = 0;
        loop_test =1;
        set_adc_channel(7); //BATT voltage
        batt_s = read_adc(adc_start_and_read);
        printf("Testing ... %lu tmr3: %lu batt: %luV\r\n",
                ++sec, tmr3, (int16)(batt_s * ADC_CONST * BATT_MUL));

        set_adc_channel(8);
        kpa_1 = read_adc(adc_start_and_read);
        printf("KPA1: %lu %lukPa\r\n", kpa_1, adc_to_kpa(kpa_1));
        set_adc_channel(9);
        kpa_2 = read_adc(adc_start_and_read);
        printf("KPA2: %lu %lukPa\r\n", kpa_2, adc_to_kpa(kpa_2));

            if (have_i2c && !test_i2c_byte) {
                if(!i2c_test_rw_byte(I2C_DISPLAY_ADR)) {
                    printf("i2c rw byte -  TEST OK\r\n");
                    test_i2c_byte = 0;
                }
            }
#if 0
            if (have_i2c && !test_i2c_block) {
                if(!i2c_test_rw_block(I2C_DISPLAY_ADR)) {
                    printf("i2c rw block -  TEST OK\r\n");
                    test_i2c_block = 0;
                }
            }

            write_i2c_dev_block(I2C_DISPLAY_ADR, 0, ee_dat, 10);
            delay_ms(250);

            for (i =0; i < 5; i ++) {
                int8 tst;
                read_i2c_dev(I2C_DISPLAY_ADR, i, &tst);
                printf("rd %u - %u\r\n", i, tst);
                //delay_ms(50);
            }
#endif
        }

        set_adc_channel(7); //BATT voltage
        batt_s = ((ADC_CONST * BATT_MUL *
                        read_adc(adc_start_and_read))/100);
        
        set_adc_channel(8);
        kpa_1 = adc_to_kpa(read_adc(adc_start_and_read));

        set_adc_channel(9);
        kpa_2 = adc_to_kpa(read_adc(adc_start_and_read));
        
        if (ms_send_data) {
            int8 *data = &ms_data;
            ms_send_data = 0;
            for (i = 2; i < sizeof(ms_data); i++) {
                data[i]=rand();
            }
            
            ms_data.batt    = batt_s;
            ms_data.baro    = kpa_1;
            ms_data.map     = kpa_2;
            ms_data.seconds ++;
            
            for (i = 0; i < sizeof(ms_data); i++) {
                putc(data[i]);
            }
        }

        if (0) {
            RST = 0;
            delay_ms(50);
            reset_cpu();
        }
    }
}
